from contextlib import asynccontextmanager

import sentry_sdk
from fastapi import FastAPI
from fastapi.routing import APIRoute
from sqlmodel import Session
from starlette.middleware.cors import CORSMiddleware

from app.api.main import api_router
from app.core.config import settings
from app.core.db import engine, init_db, init_modelprovider_model_db


def custom_generate_unique_id(route: APIRoute) -> str:
    return f"{route.tags[0]}-{route.name}"


# Sentry 是一款强大的错误跟踪和性能监控工具，可帮助开发者实时发现、诊断和解决应用程序中的问题
if settings.SENTRY_DSN:
    sentry_sdk.init(dsn=str(settings.SENTRY_DSN), enable_tracing=True)


@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup
    with Session(engine) as session:
        init_db(session)
        init_modelprovider_model_db(session)
    yield
    # Shutdown


# title：这是 API 的标题，会在生成的 OpenAPI 文档里显示。settings.PROJECT_NAME 应该是从配置文件或者环境变量里获取的项目名称。
# openapi_url：该参数指定了 OpenAPI 规范文档的 URL 路径。settings.API_V1_STR 一般是 API 的版本前缀，像 /api/v1 这类。
# generate_unique_id_function：此参数用于提供一个自定义函数，这个函数会为每个 API 路由生成唯一的 ID。custom_generate_unique_id 就是自定义的生成唯一 ID 的函数。
# debug：设置为 True 时，会开启调试模式。调试模式下，当应用出现异常时会展示详细的错误信息，方便调试，但在生产环境建议设置为 False。
# lifespan：这个参数接受一个异步函数，用来管理应用的生命周期。lifespan 函数会在应用启动和关闭时执行特定操作，比如初始化数据库连接、关闭资源等。
app = FastAPI(
    title=settings.PROJECT_NAME,
    openapi_url=f"{settings.API_V1_STR}/openapi.json",
    generate_unique_id_function=custom_generate_unique_id,
    debug=True,
    lifespan=lifespan,
)

# Set all CORS enabled origins
if settings.BACKEND_CORS_ORIGINS:
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

app.include_router(api_router, prefix=settings.API_V1_STR)

if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000, reload=True, log_level="debug")
